﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://www.codeplex.com/EmlenMud
using System;
using System.Xml.Serialization;
using System.ComponentModel;
using System.Reflection;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BrainTechLLC.ThreadSafeObjects;
using System.Runtime.Serialization;
using System.Collections;

namespace BrainTechLLC
{
    public delegate string ReplacementDelegate(params object[] context);

    [Serializable]
    [DataContract]
    public class TextReplacement
    {
        public List<IdentifierAndValue> Replacements { get; set; }

        public string PerformReplacement(string original, params object[] context)
        {
#if NO_SILVERLIGHT
            if (Replacements == null)
                return original;

            // TODO: Enumerable
            StringBuilder sb = new StringBuilder(original);
            sb.Replace("{\n}", Environment.NewLine);

            for (int n = 0; n < Replacements.Count; n++)
            {
                IdentifierAndValue replace = Replacements[n];
                if (replace._value is string)
                {
                    string replaceString = replace._value.ToString();

                    if (replaceString.StartsWith("Prop:", StringComparison.OrdinalIgnoreCase))
                    {
                        int contextIndex = 0;
                        string propertyName;

                        if (char.IsNumber(replaceString[5]))
                        {
                            contextIndex = Convert.ToInt32(replaceString.Substring(5, 1));
                            propertyName = replaceString.Substring(7);
                        }
                        else
                        {
                            propertyName = replaceString.Substring(5);                            
                        }

                        object value;

                        if (propertyName.StartsWith("PropertyData", StringComparison.OrdinalIgnoreCase))
                        {
                            int indexPropName = propertyName.IndexOf(":");
                            PropertyDescriptor prop = context[contextIndex].GetType().PropertiesForType(true)["ThingProperties"];
                            PropertyData propData = prop.GetValue(context[contextIndex]) as PropertyData;
                            propertyName = propertyName.Substring(indexPropName+1);
                            value = propData.Read<object>(propertyName); 
                        }
                        else
                        {
                            PropertyDescriptor prop = context[contextIndex].GetType().PropertiesForType(true)[propertyName];
                            value = prop.GetValue(context[contextIndex]);
                        }

                        sb.Replace(replace._identifier, value.ToString());
                    }
                    else
                    {
                        sb.Replace(replace._identifier, replaceString);
                    }
                }
                else if (replace._value is ReplacementDelegate)
                {
                    sb.Replace(replace._identifier, ((ReplacementDelegate)replace._value)(context));
                }
                else if (replace._value is TextReplacement)
                {
                    TextReplacement subReplacement = replace._value as TextReplacement;
                    int contextIndex = 0;
                    int index = replace._identifier.IndexOf(":");
                    string propertyName;

                    if (char.IsNumber(replace._identifier[index + 1]))
                    {
                        contextIndex = Convert.ToInt32(replace._identifier.Substring(index + 1, 1));
                        propertyName = replace._identifier.Substring(index + 3);
                    }
                    else
                    {
                        propertyName = replace._identifier.Substring(index + 1);
                    }

                    while (propertyName.EndsWith("}") || propertyName.EndsWith("]"))
                        propertyName = propertyName.Substring(0, propertyName.Length - 1);

                    string s = sb.ToString();
                    int insertionIndex = s.IndexOf(replace._identifier);
                    int startIndex = insertionIndex + replace._identifier.Length;
                    int endIndex = s.IndexOf(replace._identifier, startIndex);
                    // may need to adjust by 1, etc
                    string innerTemplate = s.Substring(startIndex, endIndex - startIndex);
                    string blankOutString = s.Substring(insertionIndex, endIndex + (replace._identifier.Length) - insertionIndex);
                    sb.Replace(blankOutString, string.Empty);

                    PropertyDescriptor prop = context[contextIndex].GetType().PropertiesForType(true)[propertyName];
                    object value = prop.GetValue(context[contextIndex]);

                    StringBuilder sub = new StringBuilder();

                    IEnumerable enumerable = value as IEnumerable;
                    foreach (var v in enumerable)
                    {
                        object o = v;

                        if (o is long)
                        {
                            o = Everything.Find<IGameThing>((long)v);
                        }

                        string subString = subReplacement.PerformReplacement(innerTemplate, new object[] { context[contextIndex], o });
                        sub.Append(subString);
                    }

                    sb.Insert(insertionIndex, sub.ToString());
                }
            }

            return sb.ToString();
#else
            return string.Empty;
#endif
        }
    }
}
